void Main() { var input = File.ReadAllText(Path.Combine(Path.GetDirectoryName(Util.CurrentQueryPath), "..", "day13.txt")).Split(',').Select(long.Parse).ToArray(); var comp = new IntCodeComputer(input.ToArray()); var board = new Dictionary<(long x, long y), int>(); while (!comp.Halted){ comp.GetNext(out var x); comp.GetNext(out var y); comp.GetNext(out var t); if (!comp.Halted) board[((long)x,(long)y)] = (int)t; }; var part1 = board.Count(t => t.Value == 2); part1.Dump(); comp = new IntCodeComputer(input.ToArray()); board = new Dictionary<(long x, long y), int>(); comp._mem[0] = 2; var score = 0; do { comp.GetNext(out var x); if (x == null){ var ball = board.First(ti => ti.Value == 4).Key.x; var paddle = board.First(ti => ti.Value == 3).Key.x; comp.Input.Enqueue(ball.CompareTo(paddle)); continue; } comp.GetNext(out var y); comp.GetNext(out var t); if (x == -1 && y == 0) score = (int)t; else if (!comp.Halted) board[((long)x, (long)y)] = (int)t; } while (!comp.Halted); var part2 = score; part2.Dump(); } class IntCodeComputer { public readonly Dictionary _mem; private long ptr = 0; private long relativebase = 0; public IntCodeComputer(long[] program) { _mem = program.Select((p, i) => new { p, i = (long)(i) }).ToDictionary(o => (long)o.i, o => (long)o.p); } public readonly Queue Input = new Queue(); public bool Halted; public void GetNext(out long? output) { (int[] parmModes, int opcode) op; (int[] parmModes, int opcode) readOpCode(int opCode) => (new[] { (opCode / 100) % 10, (opCode / 1000) % 10, (opCode / 10000) % 10 }, opCode % 100); long readMem(long pos) => _mem.ContainsKey(pos) ? _mem[pos] : 0; long getParmVal(int mode, long value) => mode == 0 ? readMem(value) : mode == 2 ? readMem(relativebase + value) : value; long getParm(long parm) => getParmVal(op.parmModes[parm - 1], _mem[ptr + parm]); void setParmVal(int mode, long val, long value) { if (mode == 2) _mem[relativebase + val] = value; else _mem[val] = value; } void setParm(long parm, long val) => setParmVal(op.parmModes[parm - 1], _mem[ptr + parm], val); output = default; while (_mem[ptr] != 99) { op = readOpCode((int)_mem[ptr]); switch (op.opcode) { case 1: setParm(3, getParm(1) + getParm(2)); ptr += 4; break; case 2: setParm(3, getParm(1) * getParm(2)); ptr += 4; break; case 3: if (Input.Count() == 0) return; setParm(1, Input.Dequeue()); ptr += 2; break; case 4: output = getParm(1); ptr += 2; return; break; case 5: ptr = getParm(1) != 0 ? getParm(2) : ptr + 3; break; case 6: ptr = getParm(1) == 0 ? getParm(2) : ptr + 3; break; case 7: setParm(3, getParm(1) < getParm(2) ? 1 : 0); ptr += 4; break; case 8: setParm(3, getParm(1) == getParm(2) ? 1 : 0); ptr += 4; break; case 9: relativebase += getParm(1); ptr += 2; break; } } Halted=true; } }